package networking.performance;

import java.util.TimerTask;

public class Performance extends TimerTask {

	private double interval;
	private long currentTime;
	private long lastTime;

	private int numPacketsSendPerInterval;
	private double sendThroughputPerInterval;
	private double bytesSendPerInterval;

	private int numPacketsRecvPerInterval;
	private double recvThroughputPerInterval;
	private double bytesRecvPerInterval;

	private double intervalLatency;
	private int numPacketsDelivered;

	private final int NUM_BITS;
	private final int KILO;

	public Performance() {
		NUM_BITS = 8;
		KILO = 1024;
		currentTime = System.nanoTime();
		nulifyPerformance();
	}

	public double getInterval() {
		return interval;
	}

	public void setInterval(double interval) {
		this.interval = interval;
	}

	public double getIntervalLatency() {
		return intervalLatency;
	}

	public void setIntervalLatency(double intervalLatency) {
		this.intervalLatency = intervalLatency;
	}

	public int getNumPacketsSendPerInterval() {
		return numPacketsSendPerInterval;
	}

	public void setNumPacketsSendPerInterval(int numPacketsSendPerInterval) {
		this.numPacketsSendPerInterval = numPacketsSendPerInterval;
	}

	public double getSendThroughputPerInterval() {
		return sendThroughputPerInterval;
	}

	public void setSendThroughputPerInterval(double sendThroughputPerInterval) {
		this.sendThroughputPerInterval = sendThroughputPerInterval;
	}

	public double getBytesSendPerInterval() {
		return bytesSendPerInterval;
	}

	public void setBytesSendPerInterval(double bytesSendPerInterval) {
		this.bytesSendPerInterval = bytesSendPerInterval;
	}

	public int getNumPacketsRecvPerInterval() {
		return numPacketsRecvPerInterval;
	}

	public void setNumPacketsRecvPerInterval(int numPacketsRecvPerInterval) {
		this.numPacketsRecvPerInterval = numPacketsRecvPerInterval;
	}

	public double getRecvThroughputPerInterval() {
		return recvThroughputPerInterval;
	}

	public void setRecvThroughputPerInterval(double recvThroughputPerInterval) {
		this.recvThroughputPerInterval = recvThroughputPerInterval;
	}

	public double getBytesRecvPerInterval() {
		return bytesRecvPerInterval;
	}

	public void setBytesRecvPerInterval(double bytesRecvPerInterval) {
		this.bytesRecvPerInterval = bytesRecvPerInterval;
	}

	public int getNumPacketsDelivered() {
		return numPacketsDelivered;
	}

	public void setNumPacketsDelivered(int numPacketsDelivered) {
		this.numPacketsDelivered = numPacketsDelivered;
	}

	public void nulifyPerformance() {

		this.interval = 0;

		this.numPacketsSendPerInterval = 0;
		this.sendThroughputPerInterval = 0;
		this.bytesSendPerInterval = 0;

		this.numPacketsRecvPerInterval = 0;
		this.recvThroughputPerInterval = 0;
		this.bytesRecvPerInterval = 0;

		this.intervalLatency = 0;
		this.numPacketsDelivered = 0;

		this.currentTime = 0;
		this.lastTime = 0;

	}

	@Override
	public void run() {
		lastTime = System.nanoTime();
		this.interval = (this.lastTime - this.currentTime) / 1000000000;

		calculateLatency();
		calculateThroughout();
		printPerformance();
		nulifyPerformance();

	}

	private void printPerformance() {
		System.out.println("SEND: " + this.numPacketsSendPerInterval + " Throughput: " + this.sendThroughputPerInterval);
		System.out.println("RECV: " + this.numPacketsRecvPerInterval + " Throughput: " + this.recvThroughputPerInterval);
		System.out.println("Latency: " + this.intervalLatency);
		System.out.println("Interval Time:" + this.interval + " (s)");
		System.out.println("--------------------------------------------");

	}

	private void calculateThroughout() {
		this.sendThroughputPerInterval = calculateThroughoutInMegaBitsPerSecond(this.bytesSendPerInterval);
		this.recvThroughputPerInterval = calculateThroughoutInMegaBitsPerSecond(this.bytesRecvPerInterval);
	}

	private double calculateThroughoutInMegaBitsPerSecond(double bytes) {
		double throughput;
		throughput = bytes * NUM_BITS;
		throughput = throughput / (KILO * KILO);
		throughput = throughput / this.interval;
		return throughput;
	}

	private void calculateLatency() {
		this.intervalLatency = this.intervalLatency / this.numPacketsDelivered;
	}

}
